﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using itau.im.entidade;
using itau.im.dado;
using EnterpriseLibraryWrapper;
using itau.im.negocio;

namespace itau.im.negocio
{
    public class RelatorioProdutoBS : IRelatorioProdutoBS
    {
        public FiltroRelatorioProduto ObterFiltrosRelatorioProduto()
        {
            IProdutoFinanceiroDAO ProdutoDAO = null;
            IGrupoParametrosDAO GrupoParametroDAO = null;
            FiltroRelatorioProduto filtroRelatorioProduto = null;

            try
            {
                ProdutoDAO = DaoFactory.getProdutoFinanceiroDAO();
                GrupoParametroDAO = DaoFactory.getGrupoParametrosDAO();

                filtroRelatorioProduto = new FiltroRelatorioProduto();
                filtroRelatorioProduto.Classe = ProdutoDAO.ObterClassesProdutoFinanceiro();
                filtroRelatorioProduto.Familia = ProdutoDAO.ObterFamiliasProdutoFinanceiro();
                filtroRelatorioProduto.Produto = ProdutoDAO.ObterProdutosFinanceiros();
                filtroRelatorioProduto.GrupoParametro = GrupoParametroDAO.ObterGruposDeParametros();

                List<ProdutoFinanceiroDerivado> listaProdutoDerivado = new List<ProdutoFinanceiroDerivado>();
                foreach (ProdutoFinanceiro itemProduto in filtroRelatorioProduto.Produto)
                {
                    listaProdutoDerivado.AddRange(ProdutoDAO.ObterProdutosDerivadosPorProduto(itemProduto.CodigoProdutoFinanceiro));
                }
                filtroRelatorioProduto.ProdutoDerivado = listaProdutoDerivado;

                List<ProdutoFinanceiroAlocacao> listaProdutoAlocacao = new List<ProdutoFinanceiroAlocacao>();
                foreach (GrupoParametroAtribuicao itemGrupo in filtroRelatorioProduto.GrupoParametro)
                {
                    listaProdutoAlocacao.AddRange(GrupoParametroDAO.ObterProdutoFinanceiroAlocacaoPorGrupoParametro(itemGrupo.CodigoGrupoParametroAtribuicao));
                }
                filtroRelatorioProduto.ProdutoAlocacao = listaProdutoAlocacao;

                return filtroRelatorioProduto;
            }
            catch (DadosException ex)
            {
                EnterpriseLibraryFactory.GetExceptionHandler().HandleException(ex, "ErrosNegocios");
            }
            catch (NegociosException ex)
            {
                EnterpriseLibraryFactory.GetExceptionHandler().HandleException(ex, "ErrosNegocios");
            }
            catch (Exception ex)
            {
                EnterpriseLibraryFactory.GetExceptionHandler().HandleException(ex, "ErrosNegocios");
            }
            finally
            {
                ProdutoDAO = null;
            }

            return filtroRelatorioProduto;
        }

        public IList<RelatorioSubProdPorGrupoParamSaida> ConsultarRelatorioSubProdPorGrupoParam(RelatorioSubProdPorGrupoParamEntrada filtroRelatorio, int numeroPagina, int qtdeRegistros)
        {
            IParametroAtribuicaoDAO relatorioParametroDAO = null;
            IProdutoFinanceiroDAO relatorioProdutoDAO = null;
            IRegraAtribuicaoDAO relatorioRegraDAO = null;
            IGrupoParametrosDAO relatorioGrupoParametroDAO = null;
            ICurvaDAO relatorioCurvaDAO = null;

            IList<RelatorioSubProdPorGrupoParamSaida> relatorioSubProdPorGrupoParamSaida = null;

            IList<Curva> listaCurvas;
            IList<ParametroAtribuicao> listaParametros;
            IList<DominioParametroAtribuicao> listaRegistroDominio;

            try
            {
                relatorioSubProdPorGrupoParamSaida = new List<RelatorioSubProdPorGrupoParamSaida>();

                relatorioParametroDAO = DaoFactory.getParametroAtribuicaoDAO();
                relatorioProdutoDAO = DaoFactory.getProdutoFinanceiroDAO();
                relatorioRegraDAO = DaoFactory.getRegraAtribuicaoDAO();
                relatorioGrupoParametroDAO = DaoFactory.getGrupoParametrosDAO();
                relatorioCurvaDAO = DaoFactory.getCurvaDAO();

                listaCurvas = relatorioCurvaDAO.ObterCurvas();
                listaParametros = relatorioParametroDAO.ObterParametros();
                listaRegistroDominio = relatorioParametroDAO.ObterRegistrosDominio();

                IList<RegraAtribuicaoCurvaRelatorio> regrasPorGrupo = relatorioRegraDAO.ObterRegrasAtribuicaoCurvaPorCodGrupoDataPAGINADO(filtroRelatorio.GrupoParametro.CodigoGrupoParametroAtribuicao, filtroRelatorio.DataInicioVigencia, filtroRelatorio.DataFimVigencia, numeroPagina, qtdeRegistros);
                IList<DominioParametroAtribuicao> dominiosPorGrupo = relatorioGrupoParametroDAO.ObterDominiosParametrosAtribuicaoPorGrupoVigente(filtroRelatorio.GrupoParametro.CodigoGrupoParametroAtribuicao);
                IList<ParametroAtribuicaoGrupoAlocacao> parametrosEndogenosPorGrupo = relatorioGrupoParametroDAO.ObterParametrosAtribuicaoGrupoAlocacaoPorGrupoParametrosVigente(filtroRelatorio.GrupoParametro.CodigoGrupoParametroAtribuicao);
                IList<ProdutoFinanceiroDerivado> produtosExcecaoPorGrupo = relatorioGrupoParametroDAO.ObterProdutosFinanceirosDerivadosExcecaoPorGrupoParametrosVigente(filtroRelatorio.GrupoParametro.CodigoGrupoParametroAtribuicao);

                foreach (RegraAtribuicaoCurvaRelatorio itemRegra in regrasPorGrupo)
                {
                    //Trata apenas as regras com SubProduto de Exceção listado no filtro SubProdutos
                    //if (filtroRelatorio.ListaProdutoAlocacao.Exists(p => p.CodigoProdutoFinanceiroDerivado == itemRegra.CodigoProdutoFinanceiroExcecao))
                    {
                        RelatorioSubProdPorGrupoParamSaida novoItemRelatorio = new RelatorioSubProdPorGrupoParamSaida();
                        novoItemRelatorio.ListaParametros = new List<ParametroRelatorio>();

                        IList<ParametroRegra> parametrosPorRegra = relatorioRegraDAO.ObterParametrizacoesAtribuicaoPorCodigoRegraEDataVigenciaCompleto(itemRegra.CodigoRegraAtribuicaoCurva, itemRegra.DataInicioVigencia);
                        IEnumerable<ParametroRegra> parametrosExogenosPorRegra = parametrosPorRegra.Where(p => parametrosEndogenosPorGrupo.Count(q => q.CodigoParametroAtribuicao == p.CodigoParametroAtribuicao) == 0);

                        //Curva primeiraCurva = listaCurvas.FirstOrDefault(p => p.CodigoCurva == itemRegra.CodigoCurvaPrimeira);
                        //Curva primeiraCurvaCaixa = listaCurvas.FirstOrDefault(p => p.CodigoCurva == itemRegra.CodigoCurvaPrimeiraComCaixa);
                        //Curva terceiraCurva = listaCurvas.FirstOrDefault(p => p.CodigoCurva == itemRegra.CodigoCurvaTerceira);
                        //Curva terceiraCurvaCaixa = listaCurvas.FirstOrDefault(p => p.CodigoCurva == itemRegra.CodigoCurvaTerceiraComCaixa);
                        //ProdutoFinanceiroDerivado produtoExcecao = produtosExcecaoPorGrupo.FirstOrDefault(p => p.CodigoProdutoFinanceiroDerivado == itemRegra.CodigoProdutoFinanceiroExcecao);

                        //novoItemRelatorio.NomeCurva = primeiraCurva != null ? primeiraCurva.NomeCurva : string.Empty;
                        //novoItemRelatorio.NomeCurvaComCaixa = primeiraCurvaCaixa != null ? primeiraCurvaCaixa.NomeCurva : string.Empty;
                        //novoItemRelatorio.NomeTerceiraCurva = terceiraCurva != null ? terceiraCurva.NomeCurva : string.Empty;
                        //novoItemRelatorio.NomeTerceiraCurvaComCaixa = terceiraCurva != null ? terceiraCurva.NomeCurva : string.Empty;


                        novoItemRelatorio.NomeGrupoParametro = filtroRelatorio.GrupoParametro.NomeGrupoParametroAtribuicao;
                        novoItemRelatorio.Situacao = itemRegra.CodigoSituacao == 1 ? "Habilitada" : "Desabilitada";
                        novoItemRelatorio.DataInicioVigencia = itemRegra.DataInicioVigencia;
                        novoItemRelatorio.DataFimVigencia = itemRegra.DataFimVigencia;
                        novoItemRelatorio.NomeCurva = itemRegra.NomeCurvaPrimeira;
                        novoItemRelatorio.NomeCurvaComCaixa = itemRegra.NomePrimeiraCurvaComCaixa;
                        novoItemRelatorio.NomeTerceiraCurva = itemRegra.NomeTerceiraCurva;
                        novoItemRelatorio.NomeTerceiraCurvaComCaixa = itemRegra.NomeTerceiraCurvaComCaixa;
                        novoItemRelatorio.NomeProdutoExcecao = itemRegra.NomeProdutoDerivadoExcecao;

                        switch (itemRegra.CodigoTipoPrazo)
                        {
                            case 1:
                                novoItemRelatorio.CodigoTipoPrazo = "DU";
                                break;
                            case 2:
                                novoItemRelatorio.CodigoTipoPrazo = "DC";
                                break;
                            default:
                                novoItemRelatorio.CodigoTipoPrazo = string.Empty;
                                break;
                        }
                        novoItemRelatorio.QtdeDiasPrazo = itemRegra.QuantidadeDiasPrazo;

                        //NAO APAGAR
                        //foreach (var itemEndogeno in parametrosEndogenosPorGrupo)
                        //{
                        //    ParametroAtribuicao parametroCompleto = listaParametros.FirstOrDefault(p => p.CodigoParametroAtribuicao == itemEndogeno.CodigoParametroAtribuicao);

                        //    novoItemRelatorio.ListaParametros.AddRange(ObterParametroEndogeno(itemEndogeno, parametroCompleto, dominiosPorGrupo));
                        //}

                        foreach (var itemExogeno in parametrosExogenosPorRegra)
                        {
                            ParametroAtribuicao parametroCompleto = listaParametros.FirstOrDefault(p => p.CodigoParametroAtribuicao == itemExogeno.CodigoParametroAtribuicao);

                            //IList<DominioParametroAtribuicao> dominioPorParametro = relatorioParametroDAO.ObterRegistrosDominioParametro(itemExogeno.CodigoParametroAtribuicao);
                            IList<DominioParametroAtribuicao> dominioPorParametro = listaRegistroDominio.Where(p => p.CodigoParametroAtribuicao == itemExogeno.CodigoParametroAtribuicao).ToList();

                            novoItemRelatorio.ListaParametros.AddRange(ObterParametroExogeno(itemExogeno, parametroCompleto, dominioPorParametro));
                        }

                        relatorioSubProdPorGrupoParamSaida.Add(novoItemRelatorio);
                    }

                }

                return relatorioSubProdPorGrupoParamSaida;
            }
            catch (DadosException ex)
            {
                EnterpriseLibraryFactory.GetExceptionHandler().HandleException(ex, "ErrosNegocios");
            }
            catch (NegociosException ex)
            {
                EnterpriseLibraryFactory.GetExceptionHandler().HandleException(ex, "ErrosNegocios");
            }
            catch (Exception ex)
            {
                EnterpriseLibraryFactory.GetExceptionHandler().HandleException(ex, "ErrosNegocios");
            }
            finally
            {
                relatorioProdutoDAO = null;
            }

            return relatorioSubProdPorGrupoParamSaida;
        }

        private IList<ParametroRelatorio> ObterParametroEndogeno(ParametroAtribuicaoGrupoAlocacao parametroAlocado, ParametroAtribuicao parametroCompleto, IList<DominioParametroAtribuicao> dominios)
        {
            IList<ParametroRelatorio> parametroRelatorio = new List<ParametroRelatorio>();

            if (parametroAlocado != null && parametroCompleto != null)
            {
                if (parametroAlocado.CodigoDominioParametroAtribuicao != 0)
                {
                    DominioParametroAtribuicao dominioDefinido = dominios.FirstOrDefault(p => p.CodigoDominioParametroAtribuicao == parametroAlocado.CodigoDominioParametroAtribuicao);

                    if (dominioDefinido != null)
                    {
                        parametroRelatorio.Add(new ParametroRelatorio()
                        {
                            Valor = dominioDefinido.TextoValorDominioParametro,
                            NomeParametro = parametroCompleto.NomeParametroAtribuicao
                        });
                    }
                }
                else
                {
                    if (string.IsNullOrEmpty(parametroAlocado.TextoValorAtribuicaoFim) &&
                        string.IsNullOrEmpty(parametroAlocado.TextoValorAtribuicaoFim.Trim())) //Parâmetro sem range
                    {
                        parametroRelatorio.Add(new ParametroRelatorio()
                        {
                            Valor = parametroAlocado.TextoValorParametroAtribuicao,
                            NomeParametro = parametroCompleto.NomeParametroAtribuicao
                        });
                    }
                    else //Parâmetro com range
                    {
                        parametroRelatorio.Add(new ParametroRelatorio()
                        {
                            Valor = parametroAlocado.TextoValorParametroAtribuicao,
                            NomeParametro = string.Concat(parametroCompleto.NomeParametroAtribuicao, " - ", "Início")
                        });

                        parametroRelatorio.Add(new ParametroRelatorio()
                        {
                            Valor = parametroAlocado.TextoValorAtribuicaoFim,
                            NomeParametro = string.Concat(parametroCompleto.NomeParametroAtribuicao, " - ", "Fim")
                        });
                    }
                }
            }

            return parametroRelatorio;
        }

        private IList<ParametroRelatorio> ObterParametroExogeno(ParametroRegra parametroAlocado, ParametroAtribuicao parametroCompleto, IList<DominioParametroAtribuicao> dominios)
        {
            IList<ParametroRelatorio> parametroRelatorio = new List<ParametroRelatorio>();

            if (parametroAlocado != null && parametroCompleto != null)
            {
                if (parametroAlocado.CodigoDominioParametroAtribuicao != 0)
                {
                    DominioParametroAtribuicao dominioSelecionado = dominios.FirstOrDefault(
                        p => p.CodigoDominioParametroAtribuicao == parametroAlocado.CodigoDominioParametroAtribuicao);

                    parametroRelatorio.Add(new ParametroRelatorio()
                    {
                        CodigoParametro = parametroAlocado.CodigoParametroAtribuicao,
                        CodigoDominio = parametroAlocado.CodigoDominioParametroAtribuicao,
                        Valor = dominioSelecionado.TextoValorDominioParametro,
                        NomeParametro = parametroCompleto.NomeParametroAtribuicao
                    });
                }
                else
                {
                    if (string.IsNullOrEmpty(parametroAlocado.TextoValorInternoFim) &&
                        string.IsNullOrEmpty(parametroAlocado.TextoValorInternoFim.Trim())) //Parâmetro sem range
                    {
                        parametroRelatorio.Add(new ParametroRelatorio()
                        {
                            CodigoParametro = parametroAlocado.CodigoParametroAtribuicao,
                            Valor = parametroAlocado.TextoValorInterno,
                            NomeParametro = parametroCompleto.NomeParametroAtribuicao
                        });
                    }
                    else //Parâmetro com range
                    {
                        parametroRelatorio.Add(new ParametroRelatorio()
                        {
                            CodigoParametro = parametroAlocado.CodigoParametroAtribuicao,
                            Valor = parametroAlocado.TextoValorInterno,
                            NomeParametro = string.Concat(parametroCompleto.NomeParametroAtribuicao, " - ", "Início")
                        });

                        parametroRelatorio.Add(new ParametroRelatorio()
                        {
                            CodigoParametro = parametroAlocado.CodigoParametroAtribuicao,
                            Valor = parametroAlocado.TextoValorInternoFim,
                            NomeParametro = string.Concat(parametroCompleto.NomeParametroAtribuicao, " - ", "Fim")
                        });
                    }
                }
            }

            return parametroRelatorio;
        }
    }
}
